package com.dlc.shop.platform.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dlc.shop.bean.dto.wukong.*;
import com.dlc.shop.bean.enums.SendUserTypeEnum;
import com.dlc.shop.bean.model.ImChannel;
import com.dlc.shop.bean.model.User;
import com.dlc.shop.bean.vo.wukong.*;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.enums.SysTypeEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.response.ResponseEnum;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.common.wukongim.constant.WuKongConstant;
import com.dlc.shop.security.common.util.AuthUserContext;
import com.dlc.shop.service.ImChannelService;
import com.dlc.shop.service.UserService;
import com.dlc.shop.sys.common.model.SysUser;
import com.dlc.shop.sys.common.service.SysUserService;
import com.dlc.shop.wukongim.service.WuKongImService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author TRACK
 */
@RestController
@AllArgsConstructor
@RequestMapping("/platform/wuKongIm")
@Tag(name = "平台客服接口")
public class WuKongImController {

    private final WuKongImService wuKongImService;
    private final SysUserService sysUserService;
    private final ImChannelService imChannelService;
    private final UserService userService;

    @PostMapping("/registerOrLogin")
    @Operation(summary = "用户注册或登录到im")
    public ServerResponseEntity<RegisterOrLoginVO> registerOrLogin() {
        Long sysUserId = AuthUserContext.getSysUserId();
        List<String> list = StpUtil.getTokenValueListByLoginId(AuthUserContext.getUid());
        // 使用最开始登录的token
        String token = list.get(0);
        SysUser sysUser = checkAndGetEmployee(sysUserId);
        String uid = WuKongConstant.getSysUid(sysUserId);
        // 平台客服支持多开消息盒子窗口
        RegisterOrLoginDTO registerOrLoginDTO = new RegisterOrLoginDTO(uid, token, 1, 0);
        wuKongImService.registerOrLogin(registerOrLoginDTO);
        return ServerResponseEntity.success(new RegisterOrLoginVO(uid, token));
    }

    private SysUser checkAndGetEmployee(Long sysUserId) {
        SysUser sysUser = sysUserService.getSysUserById(sysUserId);
        if (Objects.isNull(sysUser)) {
            // 该账号不存在
            throw new YamiShopBindException("yami.phone.number.not.exists");
        }
        if (Objects.equals(sysUser.getStatus(), 0)) {
            throw new YamiShopBindException("用户已被禁用");
        }
        return sysUser;
    }

    @PostMapping("/createChannel")
    @Operation(summary = "用户与平台创建频道", description = "平台首次发消息时调用")
    @Parameter(name = "userId", description = "用户id", required = true)
    public ServerResponseEntity<ChannelVO> createChannel(@RequestParam("userId") String userId) {
        Long sysUserId = AuthUserContext.getSysUserId();
        // 频道id，用户id+店铺id
        String channelId = WuKongConstant.getChannelId(userId, AuthUserContext.getShopId());
        List<String> subscribers = new ArrayList<>();
        subscribers.add(WuKongConstant.USER + userId);
        subscribers.add(WuKongConstant.getSysUid(sysUserId));
        if (!Objects.equals(Constant.SUPER_ADMIN_ID, sysUserId)) {
            // 超管加入订阅者
            subscribers.add(WuKongConstant.getSysUid(Constant.SUPER_ADMIN_ID));
        }
        ChannelDTO channelDTO = new ChannelDTO(channelId, WuKongConstant.GROUP_CHAT, 0, subscribers);
        // 组装结果
        ChannelVO channelVO = getChannelVO(userId, channelId);
        // 创建频道
        ImChannel imChannel = new ImChannel(channelId, AuthUserContext.getShopId(), userId, sysUserId);
        imChannelService.createChannel(imChannel, channelDTO, channelVO.getNickName());
        return ServerResponseEntity.success(channelVO);
    }

    private ChannelVO getChannelVO(String userId, String channelId) {
        ChannelVO channelVO = new ChannelVO(channelId);
        channelVO.setUid(WuKongConstant.USER + userId);
        User user = userService.getUserByUserId(userId);
        if (Objects.isNull(user)) {
            throw new YamiShopBindException("用户已注销");
        }
        channelVO.setNickName(user.getNickName());
        channelVO.setPic(user.getPic());
        return channelVO;
    }

    @GetMapping("/listTransfer")
    @Operation(summary = "获取可转接客服列表")
    @PreAuthorize("@pms.hasPermission('platform:im:listTransfer')")
    public ServerResponseEntity<List<SubscriberVO>> listTransfer() {
        Long sysUserId = AuthUserContext.getSysUserId();
        List<Long> sysUserIds = sysUserService.listSysUserIds();
        sysUserIds.remove(sysUserId);
        if (CollUtil.isEmpty(sysUserIds)) {
            return ServerResponseEntity.success(new ArrayList<>());
        }
        List<Long> onlineSysUserIds = wuKongImService.listOnlineManagerIds(sysUserIds, AuthUserContext.getShopId());
        if (CollUtil.isEmpty(onlineSysUserIds)) {
            return ServerResponseEntity.success(new ArrayList<>());
        }
        List<SubscriberVO> res = new ArrayList<>(onlineSysUserIds.size());
        for (Long onlineSysUserId : onlineSysUserIds) {
            SysUser sysUser = sysUserService.getSysUserById(onlineSysUserId);
            SubscriberVO subscriberVO = new SubscriberVO(WuKongConstant.getSysUid(onlineSysUserId), sysUser.getNickName(), null);
            res.add(subscriberVO);
        }
        return ServerResponseEntity.success(res);
    }

    @PostMapping("/transfer")
    @Operation(summary = "转接客服")
    @Parameters({
            @Parameter(name = "uid", description = "转接客服的uid", required = true),
            @Parameter(name = "channelId", description = "频道id", required = true)
    })
    @PreAuthorize("@pms.hasPermission('platform:im:transfer')")
    public ServerResponseEntity<Void> transfer(@RequestParam("uid") String uid, @RequestParam("channelId") String channelId) {
        if (!Objects.equals(WuKongConstant.getShopId(channelId), AuthUserContext.getShopId())) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        Long sysUserId = WuKongConstant.getSysUserId(uid);
        SysUser sysUser = checkAndGetEmployee(sysUserId);
        List<Long> onlineManagerIds = wuKongImService.listOnlineManagerIds(Collections.singletonList(sysUserId), AuthUserContext.getShopId());
        if (CollUtil.isEmpty(onlineManagerIds)) {
            throw new YamiShopBindException("客服当前不在线，请刷新页面重试");
        }
        ImChannel imChannel = imChannelService.getByChannelId(channelId);
        imChannel.setEmployeeId(sysUserId);
        imChannelService.updateChannel(imChannel, uid, sysUser.getNickName());
        return ServerResponseEntity.success();
    }

    @GetMapping("/conversation/sync/page")
    @Operation(summary = "分页获取用户最近会话列表")
    @PreAuthorize("@pms.hasPermission('platform:im:listConversation')")
    public ServerResponseEntity<IPage<ConversationSyncVO>> conversationSyncPage(PageParam<ConversationSyncVO> pageParam, ConversationSyncDTO conversationSyncDTO) {
        String uid = WuKongConstant.getSysUid(AuthUserContext.getSysUserId());
        conversationSyncDTO.setUid(uid);
        conversationSyncDTO.setMsg_count(1);
        List<ConversationSyncVO> conversationSyncList = wuKongImService.conversationSync(conversationSyncDTO);
        IPage<ConversationSyncVO> page = new PageParam<>();
        page.setTotal(conversationSyncList.size());
        page.setSize(pageParam.getSize());
        page.setCurrent(pageParam.getCurrent());
        long totalPages = page.getTotal() % pageParam.getSize() == 0 ?
                page.getTotal() / pageParam.getSize() : (page.getTotal() / pageParam.getSize() + 1);
        page.setPages(totalPages);
        page.setRecords(new ArrayList<>());
        if (CollUtil.isNotEmpty(conversationSyncList)) {
            int start = Math.min((int)(pageParam.getSize() * (pageParam.getCurrent() - 1)), conversationSyncList.size());
            int end = Math.min(start + (int)pageParam.getSize(), conversationSyncList.size());
            List<ConversationSyncVO> subList = new ArrayList<>();
            if (start < end) {
                subList = conversationSyncList.subList(start, end);
            }
            if (CollUtil.isNotEmpty(subList)) {
                Set<String> userIds = subList.stream().map(con -> WuKongConstant.getUserId(con.getChannelId())).collect(Collectors.toSet());
                List<User> userList = userService.getUserByUserIds(new ArrayList<>(userIds));
                Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getUserId, u -> u));
                for (ConversationSyncVO conversationSyncVO : subList) {
                    String userId = WuKongConstant.getUserId(conversationSyncVO.getChannelId());
                    conversationSyncVO.setUserId(userId);
                    conversationSyncVO.setIsDestroy(0);
                    User user = userMap.get(userId);
                    if (Objects.isNull(user)) {
                        conversationSyncVO.setNickName("用户已注销");
                        conversationSyncVO.setIsDestroy(1);
                        continue;
                    }
                    conversationSyncVO.setNickName(user.getNickName());
                    conversationSyncVO.setPic(user.getPic());
                }
            }
            page.setRecords(subList);
        }
        return ServerResponseEntity.success(page);
    }

    @PostMapping("/conversations/setUnread")
    @Operation(summary = "标记频道为已读", description = "点进频道时请求")
    public ServerResponseEntity<Void> setUnread(@RequestBody @Valid SetUnreadDTO setUnreadDTO) {
        if (!Objects.equals(AuthUserContext.getShopId(), WuKongConstant.getShopId(setUnreadDTO.getChannel_id()))) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        if (Objects.isNull(setUnreadDTO.getMaxSeq())) {
            throw new YamiShopBindException("已读的最大消息序号不能为空");
        }
        String uid = WuKongConstant.getSysUid(AuthUserContext.getSysUserId());
        setUnreadDTO.setUid(uid);
        setUnreadDTO.setUnread(0);
        setUnreadDTO.setChannel_type(WuKongConstant.GROUP_CHAT);
        imChannelService.setUnread(setUnreadDTO, SysTypeEnum.PLATFORM.value());
        return ServerResponseEntity.success();
    }

    @PostMapping("/updateAuto")
    @Operation(summary = "更新自动回复")
    public ServerResponseEntity<Void> updateAuto(@RequestParam("channelId") String channelId) {
        if (!Objects.equals(WuKongConstant.getShopId(channelId), AuthUserContext.getShopId())) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        imChannelService.updateAuto(channelId, 0, null, null);
        return ServerResponseEntity.success();
    }

    @PostMapping("/channel/messageSync")
    @Operation(summary = "获取用户频道消息列表")
    @PreAuthorize("@pms.hasPermission('platform:im:listMessage')")
    public ServerResponseEntity<MessageSyncVO> messageSync(@RequestBody @Valid MessageSyncDTO messageSyncDTO) {
        if (!Objects.equals(AuthUserContext.getShopId(), WuKongConstant.getShopId(messageSyncDTO.getChannel_id()))) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        String uid = WuKongConstant.getSysUid(AuthUserContext.getSysUserId());
        messageSyncDTO.setLogin_uid(uid);
        messageSyncDTO.setChannel_type(WuKongConstant.GROUP_CHAT);
        MessageSyncVO messageSyncVO = wuKongImService.messageSync(messageSyncDTO);
        return ServerResponseEntity.success(messageSyncVO);
    }

    @GetMapping("/listChannelSubcribers")
    @Operation(summary = "获取用户频道订阅者信息")
    public ServerResponseEntity<ImChannelVO> listChannelSubcribers(@RequestParam("channelId") String channelId) {
        Long shopId = WuKongConstant.getShopId(channelId);
        if (!Objects.equals(shopId, AuthUserContext.getShopId())) {
            throw new YamiShopBindException(ResponseEnum.UNAUTHORIZED);
        }
        ImChannel imChannel = imChannelService.getByChannelId(channelId);
        String userId = imChannel.getUserId();
        if (Objects.isNull(imChannel)) {
            throw new YamiShopBindException("频道不存在");
        }
        if (!Objects.equals(imChannel.getShopId(), shopId)) {
            throw new YamiShopBindException("当前频道不属于你");
        }
        ImChannelVO imChannelVO = new ImChannelVO();
        imChannelVO.setChannelId(imChannel.getChannelId());
        imChannelVO.setShopId(shopId);
        List<Long> subscribers = Arrays.stream(imChannel.getSubscribers().split(StrUtil.COMMA))
                .map(id -> Long.parseLong(id)).sorted().collect(Collectors.toList());
        List<SubscriberVO> result = new ArrayList<>(subscribers.size());
        List<Long> listOnlineManagerIds = wuKongImService.listOnlineManagerIds(subscribers, shopId);
        imChannelVO.setShopName(Constant.PLATFORM_SHOP_NAME);
        for (Long subscriber : subscribers) {
            SysUser sysUser = sysUserService.getSysUserById(subscriber);
            if (Objects.isNull(sysUser)) {
                continue;
            }
            SubscriberVO subscriberVO = new SubscriberVO();
            subscriberVO.setShopId(shopId);
            subscriberVO.setUid(WuKongConstant.getSysUid(subscriber));
            subscriberVO.setIsWhiteListUser(Objects.equals(imChannel.getEmployeeId(), subscriber) ? 1 : 0);
            subscriberVO.setIsOnline(listOnlineManagerIds.contains(subscriber) ? 1 : 0);
            subscriberVO.setSendUserType(SendUserTypeEnum.PLATFORM.value());
            subscriberVO.setNickName(sysUser.getNickName());
            subscriberVO.setStatus(sysUser.getStatus());
            result.add(subscriberVO);
        }
        // 组装用户信息
        User user = userService.getUserByUserId(userId);
        if (Objects.isNull(user)) {
            user = new User();
            user.setNickName("用户已注销");
        }
        String uid = WuKongConstant.USER + userId;
        Integer userOnline = wuKongImService.getUserOnline(uid) ? 1 : 0;
        SubscriberVO subscriberVO = new SubscriberVO(uid, user.getNickName(), user.getPic(), 1, userOnline, SendUserTypeEnum.ORDINARY.value());
        subscriberVO.setUserId(userId);
        result.add(subscriberVO);
        imChannelVO.setSubscribers(result);
        return ServerResponseEntity.success(imChannelVO);
    }

    @PostMapping("/getShopChannelInfo")
    @Operation(summary = "获取用户与商家的频道信息")
    @PreAuthorize("@pms.hasPermission('platform:im:getInfo')")
    @Parameter(name = "userId", description = "用户id", required = true)
    public ServerResponseEntity<ChannelVO> getShopChannelInfo(@RequestParam(value = "userId") String userId) {
        ImChannel imChannel = imChannelService.getByChannelId(WuKongConstant.getChannelId(userId, AuthUserContext.getShopId()));
        if (Objects.isNull(imChannel)) {
            return ServerResponseEntity.success();
        }
        ChannelVO channelVO = new ChannelVO();
        channelVO.setIsWhiteUser(Objects.equals(imChannel.getEmployeeId(), AuthUserContext.getSysUserId())? 1 : 0);
        SysUser sysUser = sysUserService.getSysUserById(imChannel.getEmployeeId());
        channelVO.setEmployeeName(sysUser.getNickName());
        User user = userService.getUserByUserId(userId);
        if (Objects.isNull(user)) {
            channelVO.setNickName("用户已注销");
            channelVO.setIsDestroy(1);
            channelVO.setUserIsOnline(0);
        } else {
            channelVO.setNickName(user.getNickName());
            channelVO.setPic(user.getPic());
            channelVO.setIsDestroy(0);
            Boolean userOnline = wuKongImService.getUserOnline(WuKongConstant.USER + userId);
            channelVO.setUserIsOnline(userOnline ? 1 : 0);
        }
        channelVO.setImChannel(imChannel);
        return ServerResponseEntity.success(channelVO);
    }
}
